/*
 *  Copyright (C), 2015-2024
 *  FileName: curve_charts
 *  Author: Tonight丶相拥
 *  Date: 5/21/24
 *  Description: 
 **/

part of appcommon;

class CurveChartsPainter extends CustomPainter {
  CurveChartsPainter(this.values, this.maxValue, {this.location = 8, this.gap = 32, this.gradient});
  final List<int> values;
  final int maxValue;
  final double location;
  final double gap;
  final Gradient? gradient;

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..style = PaintingStyle.stroke;
    Path path = Path();
    path.moveTo(0, 0);
    // print(size);
    path.lineTo(0, size.height);
    path.lineTo(size.width, size.height);
    canvas.drawPath(path, paint);

    Path valuePath = Path();
    Paint paint1 = Paint()..style = PaintingStyle.stroke;
    // double location = 8;
    // double gap = 32;
    if (values.isNotEmpty) {
      var firstValue = values.first;
      valuePath.moveTo(location, size.height - size.height / maxValue * firstValue);
    }

    for (int i = 0; i < values.length; i ++) {
      if (i == 0) {
        continue;
      }
      var value = values[i];
      var valueX = location + gap * i;
      var valueY = size.height - size.height / maxValue * value;
      var valuePre = values[i - 1];
      var valuePX = location + gap * (i- 1);
      var valuePY = size.height - size.height / maxValue * valuePre;
      // valuePath.cubicTo((valuePX + valueX) / 2, valuePY, (valuePX + valueX) / 2, valueY, valueX, valueY);
      _cubicTo(valuePath, pointPre: math.Point<double>(valuePX, valuePY), point: math.Point<double>(valueX, valueY));
    }

    var pathMetrics = valuePath.computeMetrics(forceClosed: false);
    var list = pathMetrics.toList();
    var listLength = list.length.toInt();
    var linePath = Path();
    var shaderPath = Path();
    for (int i = 0; i < listLength; i ++) {
      var extractPath = list[i].extractPath(0, list[i].length, startWithMoveTo: true);
      shaderPath = extractPath;
      linePath.addPath(extractPath, const Offset(0, 0));
    }

    canvas.drawPath(linePath, paint1);
    _drawShader(canvas, shaderPath, Rect.fromLTWH(location, 0, gap * (values.length - 1), size.height));
  }

  ///弧线
  /// pointPre: 前一个点
  /// point: 后一个点
  void _cubicTo(Path valuePath, {required math.Point<double> pointPre, required math.Point<double> point}){
    valuePath.cubicTo((pointPre.x + point.x) / 2, pointPre.y, (pointPre.x + point.x) / 2, point.y, point.x, point.y);
  }

  ///绘制阴影
  void _drawShader(Canvas canvas, Path shadowPath, Rect rect) {
    // var shader = LinearGradient(
    //     begin: Alignment.topCenter,
    //     end: Alignment.bottomCenter,
    //     tileMode: TileMode.repeated,
    //     colors: [
    //       Colors.deepPurple.withOpacity(0.5),
    //       Colors.red.withOpacity(0.5),
    //       Colors.cyan.withOpacity(0.5),
    //       Colors.deepPurpleAccent.withOpacity(0.5),
    //     ]).createShader(rect);
    if (gradient == null){
      return;
    }
    var shader = gradient?.createShader(rect);

    ///从path的最后一个点连接起始点，形成一个闭环
    shadowPath
      ..lineTo(rect.right, rect.height)
      ..lineTo(rect.left, rect.height)
      ..close();

    canvas.drawPath(shadowPath, Paint()
      ..shader = shader
      ..isAntiAlias = true
      ..style = PaintingStyle.fill);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    if (oldDelegate is CurveChartsPainter) {
      // print('2222: ${oldDelegate.values} === ${oldDelegate.maxValue} ====== $values === $maxValue ==== ${oldDelegate.hashCode} ==== ${this.hashCode}');
      return oldDelegate.values != values || oldDelegate.maxValue != maxValue
          || oldDelegate.gap != gap || oldDelegate.location != location
          || oldDelegate.gradient != gradient;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(this.values, this.maxValue, this.location, this.gap, this.gradient);
}